﻿using DBModel.Context;
using Microsoft.EntityFrameworkCore;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace WebApiCoreFx.Extensions
{
    public class DbMigratorHostedService : IHostedService
    {
        private readonly ILogger<DbMigratorHostedService> _logger;
        private readonly IHostApplicationLifetime _hostApplicationLifetime;
        private readonly IConfiguration _configuration;
        private readonly IServiceProvider _provider;

        public DbMigratorHostedService(
            ILogger<DbMigratorHostedService> logger,
            IHostApplicationLifetime hostApplicationLifetime,
            IConfiguration configuration,
            IServiceProvider provider
            )
        {
            _logger = logger;
            _hostApplicationLifetime = hostApplicationLifetime;
            _configuration = configuration;
            _provider = provider;
        }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            var asyncScope = _provider.CreateAsyncScope();
            var dbCtx = asyncScope.ServiceProvider.GetRequiredService<AppDBContext>();
            //await dbCtx.Database.EnsureCreatedAsync();
            await dbCtx.Database.MigrateAsync();
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            return Task.CompletedTask;
        }

        public async Task MigrateAsync()
        {
            var initialMigrationAdded = AddInitialMigrationIfNotExist();

            if (initialMigrationAdded)
            {
                return;
            }

            _logger.LogInformation("Started database migrations...");

            //await MigrateDatabaseSchemaAsync();
            //await SeedDataAsync();

            _logger.LogInformation($"Successfully completed host database migrations.");

            _logger.LogInformation("Successfully completed all database migrations.");
            _logger.LogInformation("You can safely end this process...");
        }

        private bool AddInitialMigrationIfNotExist()
        {
            //try
            //{
            //    if (!DbMigrationsProjectExists())
            //    {
            //        return false;
            //    }
            //}
            //catch (Exception)
            //{
            //    return false;
            //}

            try
            {
                if (!MigrationsFolderExists())
                {
                    AddInitialMigration();
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception e)
            {
                _logger.LogWarning("Couldn't determinate if any migrations exist : " + e.Message);
                return false;
            }
        }

        private bool MigrationsFolderExists()
        {
            var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath();
            return dbMigrationsProjectFolder != null && Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "Migrations"));
        }

        private void AddInitialMigration()
        {
            _logger.LogInformation("Creating initial migration...");
            string argumentPrefix;
            string fileName;
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                argumentPrefix = "-c";
                fileName = "/bin/bash";
            }
            else
            {
                argumentPrefix = "/C";
                fileName = "cmd.exe";
            }
            string cmd = $"{argumentPrefix} \"abp create-migration-and-run-migrator \"{GetEntityFrameworkCoreProjectFolderPath()}\"\"";
            var procStartInfo = new ProcessStartInfo(fileName, cmd);
            try
            {
                Process.Start(procStartInfo);
            }
            catch (Exception)
            {
                throw new Exception("Couldn't run ABP CLI...");
            }
        }

        private string? GetEntityFrameworkCoreProjectFolderPath()
        {
            var slnDirectoryPath = GetSolutionDirectoryPath();
            if (slnDirectoryPath == null)
            {
                throw new Exception("Solution folder not found!");
            }
            var srcDirectoryPath = Path.Combine(slnDirectoryPath, "src");
            return Directory.GetDirectories(srcDirectoryPath)
                .FirstOrDefault(d => d.EndsWith(".EntityFrameworkCore"));
        }

        private string? GetSolutionDirectoryPath()
        {
            var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());
            while (currentDirectory != null && Directory.GetParent(currentDirectory.FullName) != null)
            {
                currentDirectory = Directory.GetParent(currentDirectory.FullName);
                if (currentDirectory != null && Directory.GetFiles(currentDirectory.FullName).FirstOrDefault(f => f.EndsWith(".sln")) != null)
                {
                    return currentDirectory.FullName;
                }
            }
            return null;
        }

    }

    public class DbInitializer
    {
        public async Task InitializeAsync(AppDBContext context)
        {
            //获取未应用的Migrations，不必要，MigrateAsync方法会自动处理
            //var migrations = await context.Database.GetPendingMigrationsAsync();
            await context.Database.MigrateAsync();//根据Migrations修改/创建数据库
        }
    }
}